package com.serviceprovider.business.module.exception;

//~--- non-JDK imports --------------------------------------------------------

import com.serviceprovider.business.utility.ThreadPool;

import org.apache.log4j.Logger;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

//~--- JDK imports ------------------------------------------------------------

import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <a href="http://developingdeveloper.wordpress.com/2008/03/09/handling-exceptions-in-spring-mvc-part-2/">http://developingdeveloper.wordpress.com/2008/03/09/handling-exceptions-in-spring-mvc-part-2/</a>
 */
public class NotifyingExceptionResolver extends SimpleMappingExceptionResolver {
    public static final Logger               logger              = Logger.getLogger(EmailNotificationServiceImpl.class);
    private String                           notificationMessage = null;
    private ThreadPool                       threadPool          = new ThreadPool();
    String                                   enableSendMail;
    private Properties                       exceptionMapping;
    private Properties                       priorityExpMappings;
    private Map<String, NotificationService> priorityNSMappings;

    public void setEnableSendMail(String enableSendMail) {
        this.enableSendMail = enableSendMail;
    }

    @Override
    public void setExceptionMappings(Properties mappings) {
        exceptionMapping = mappings;
        super.setExceptionMappings(mappings);
    }

    public void setPriorityExceptionMappings(Properties priorityExpMappings) {
        this.priorityExpMappings = priorityExpMappings;
    }

    public void setPriorityNotificationServicesMappings(Map<String, NotificationService> priorityNSMappings) {
        this.priorityNSMappings = priorityNSMappings;
    }

    public void setNotificationMessage(String message) {
        this.notificationMessage = message;
    }

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
            final Exception ex) {
        logger.warn("An Exception has occured in the application", ex);

        if ("true".equalsIgnoreCase(enableSendMail)) {
            threadPool.run(new Runnable() {
                @Override
                public void run() {
                    sendNotification(ex);
                }
            });
        }

        Exception exception     = ex;
        String    exceptionView = findMatchingViewName(exceptionMapping, ex);

        if (exceptionView != null) {
            exception = new ApplicationLocalizeException(ex.getClass().getSimpleName(), ex);
        }

        return super.doResolveException(request, response, handler, exception);
    }

    private void sendNotification(Exception ex) {
        String              priority            = resolvePriority(this.priorityExpMappings, ex);
        NotificationService notificationService = resolveNotificationService(this.priorityNSMappings, priority);
        String              message             = ((notificationMessage == null)
                ? priority
                : notificationMessage);

        if (notificationService != null) {
            logger.debug("notification message was sent");
            notificationService.sendNotification(message, ex);
        }
    }

    /**
     * Resolve priority if there isn't any priority, viewName is return
     */
    private String resolvePriority(Properties priorityExpMappings, Exception ex) {
        return this.findMatchingViewName(priorityExpMappings, ex);
    }

    private NotificationService resolveNotificationService(Map<String, NotificationService> priorityNSMappings,
            String priority) {
        NotificationService notificationService = priorityNSMappings.get(priority);

        if ((notificationService != null) && logger.isDebugEnabled()) {
            logger.debug("Resolving to a notification service for priority [" + priority + "]");
        }

        return notificationService;
    }
}



